package com.ruoyi.paipan.common;

import com.ruoyi.paipan.utils.SolarUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class SolarWeek {
    private int year;
    private int month;
    private int day;
    private int start;

    public SolarWeek(int year, int month, int day, int start) {
        this.year = year;
        this.month = month;
        this.day = day;
        this.start = start;
    }


    @Override
    public String toString()
    {
        return this.year + "." + this.month + "." + this.getIndex();
    }


    public String toFullString()
    {
        return this.year + "年" + this.month + "月第" + this.getIndex() + "周";
    }

    public static SolarWeek fromYmd(int year,int month,int day,int start)
    {
        return new SolarWeek(year, month, day, start);
    }

    public static SolarWeek fromDate(Date date, int start)
    {
        Solar solar = Solar.fromDate(date);
        return new SolarWeek(solar.getYear(), solar.getMonth(), solar.getDay(), start);
    }

    public int getYear()
    {
        return this.year;
    }

    public int getMonth()
    {
        return this.month;
    }

    public int getDay()
    {
        return this.day;
    }

    public int getStart()
    {
        return this.start;
    }

    public int getIndex()
    {
        int offset = Solar.fromYmd(this.year, this.month, 1).getWeek() - this.start;
        if (offset < 0) {
            offset += 7;
        }
        return (int)Math.ceil((this.day + offset) / 7.0);
    }

    public int getIndexInYear()
    {
        int offset = Solar.fromYmd(this.year, 1, 1).getWeek() - this.start;
        if (offset < 0) {
            offset += 7;
        }
        return (int)Math.ceil((double) (SolarUtil.getDaysInYear(this.year, this.month, this.day) + offset) / 7);
    }

    public SolarWeek next(int weeks, boolean separateMonth)
    {
        if (0 == weeks) {
            return SolarWeek.fromYmd(this.year, this.month, this.day, this.start);
        }
        Solar solar = Solar.fromYmd(this.year, this.month, this.day);
        if (separateMonth) {
            int n = weeks;
            SolarWeek week = SolarWeek.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay(), this.start);
            int  month = this.month;
            boolean plus = n > 0;
            while (0 != n) {
                solar = solar.next(plus ? 7 : -7);
                week = SolarWeek.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay(), this.start);
                int weekMonth = week.getMonth();
                if (month != weekMonth) {
                    int index = week.getIndex();
                    if (plus) {
                        if (1 == index) {
                            Solar firstDay = week.getFirstDay();
                            week = SolarWeek.fromYmd(firstDay.getYear(), firstDay.getMonth(), firstDay.getDay(), this.start);
                            weekMonth = week.getMonth();
                        } else {
                            solar = Solar.fromYmd(week.getYear(), week.getMonth(), 1);
                            week = SolarWeek.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay(), this.start);
                        }
                    } else {
                        if (SolarUtil.getWeeksOfMonth(week.getYear(), week.getMonth(), week.getStart()) == index) {
                            Solar lastDay = week.getFirstDay().next(6);
                            week = SolarWeek.fromYmd(lastDay.getYear(), lastDay.getMonth(), lastDay.getDay(), this.start);
                            weekMonth = week.getMonth();
                        } else {
                            solar = Solar.fromYmd(week.year, week.month, SolarUtil.getDaysOfMonth(week.getYear(), week.getMonth()));
                            week = SolarWeek.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay(), this.start);
                        }
                    }
                    month = weekMonth;
                }
                n -= plus ? 1 : -1;
            }
            return week;
        } else {
            solar = solar.next(weeks * 7);
            return SolarWeek.fromYmd(solar.getYear(), solar.getMonth(), solar.getDay(), this.start);
        }
    }

    public Solar getFirstDay()
    {
        Solar solar = Solar.fromYmd(this.year, this.month, this.day);
        int prev = solar.getWeek() - this.start;
        if (prev < 0) {
            prev += 7;
        }
        return solar.next(-prev);
    }

    public Solar getFirstDayInMonth()
    {
        List<Solar> days = this.getDays();
        for (Solar day : days) {
            if(this.month == day.getMonth()){
                return day;
            }
        }
        return null;
    }

    public List<Solar> getDays()
    {
        Solar firstDay = this.getFirstDay();
        List<Solar> l = new ArrayList<>();
        if (null == firstDay) {
            return l;
        }
        l.add(firstDay);
        for (int i = 1; i < 7; i++) {
            l.add(firstDay.next(i));
        }
        return l;
    }

    public List<Solar> getDaysInMonth()
    {
        List<Solar> days = this.getDays();
        List<Solar> l = new ArrayList<>();
        for (Solar day : days) {
            if(this.month == day.getMonth()){
                continue;
            }
            l.add(day);
        }
        return l;
    }

    public static void main(String[] args) {
        System.out.println(SolarWeek.fromDate(new Date(), 1));
    }
}
